package generate

import (
	"math/rand"
	"time"

	"gddgame.cc/galaxy"
	"gddgame.cc/galaxy/common/bootstrap"
	"gddgame.cc/galaxy/common/dsl/game"
	"gddgame.cc/galaxy/common/dsl/game/config"
	"gddgame.cc/galaxy/common/dsl/game/user"
	"gddgame.cc/galaxy/common/feature/dwarf"
	"gddgame.cc/galaxy/common/service/generate_name"
	"gddgame.cc/galaxy/common/service/rank"
	"gddgame.cc/galaxy/core/sdk"
	"gddgame.cc/galaxy/project/maze/maze"
	"gddgame.cc/galaxy/project/maze/maze/model"
	"gddgame.cc/galaxy/project/maze/maze/model/player_model"
	"gddgame.cc/galaxy/project/maze/maze/model/player_single"
	"gddgame.cc/galaxy/utils"
	"github.com/spf13/cobra"
)

var (
	cnf    *maze.Config
	client *sdk.AppClient
	Env    *game.Environment
	ii     I
)

type I struct {
	Boot *bootstrap.Boot `inject:""`
}

var Command = &cobra.Command{
	Use:   "generate",
	Short: "生成游戏数据",
	Long:  `通过命令行生成所需游戏数据`,
}
var userCommand = &cobra.Command{
	Use:   "user [number]",
	Short: "Generate system user",
	Args:  cobra.ExactArgs(1),
	Run: func(cmd *cobra.Command, args []string) {
		if err := InitEnv(); err != nil {
			dwarf.Context.Error(err)
			return
		}
		rand.Seed(time.Now().UnixNano())

		UserData, err := user.GetUserData(Env)
		if err != nil {
			dwarf.Context.Error(err)
			return
		}

		PlayerModelData, err := player_model.GetPlayerModelData(Env)
		if err != nil {
			dwarf.Context.Error(err)
			return
		}
		PlayerSingleData, err := player_single.GetPlayerSingleData(Env)
		if err != nil {
			dwarf.Context.Error(err)
			return
		}

		rankService := rank.Default()
		rankService.RegisterRedis(ii.Boot.Redis())

		onlineLeaderboard, err := client.GetLeaderboard(model.OnlineLeaderboard)
		if err != nil {
			dwarf.Context.Error(err)
			return
		}
		onlineLeaderboardRank := rankService.GetInstance("maze", utils.ToString(onlineLeaderboard.Id), onlineLeaderboard.Asc)
		singleLeaderboard, err := client.GetLeaderboard(model.SingleLeaderboard)
		if err != nil {
			dwarf.Context.Error(err)
			return
		}
		singleLeaderboardRank := rankService.GetInstance("maze", utils.ToString(singleLeaderboard.Id), singleLeaderboard.Asc)

		number := utils.ToInt(args[0])
		for i := 0; i < number; i++ {
			userOpen, err := client.RegisterGuest()
			if err != nil {
				dwarf.Context.Error(err)
				return
			}
			var user model.User
			_, err = UserData.FindOrCreateUser(userOpen.Id, &user, func() {
				user.OpenId = userOpen.Id
				user.BaseId = model.DefaultBaseId
				m := PlayerModelData.Random()
				user.Entity = m.Key
				user.IsSystem = true
				user.OnlineScore = int(rand.Int31n(100))
				name := ""
				if rand.Int31n(2) > 0 {
					name = generate_name.RandomEnglish()
				} else {
					name = generate_name.RandomChinese()
				}
				_ = client.ChangeOpen(userOpen.Id, name, user.Entity)
				userOpen.NickName = name
				userOpen.Avatar = user.Entity
			})
			if err != nil {
				dwarf.Context.Error(err)
				return
			}
			// 更新联机排行榜
			if _, err := client.UpdateLeaderboard(userOpen.Id, onlineLeaderboard, user.OnlineScore); err != nil {
				return
			}
			if err := onlineLeaderboardRank.Update(userOpen.Id, user.OnlineScore); err != nil {
				return
			}

			// 生成关卡排行榜
			for _, single := range PlayerSingleData.Singles {
				time := single.BaseTime + rand.Intn(5)
				star := rand.Intn(3) + 1
				score := (single.BaseTime + (single.BaseTime - time)) * (star/2 + 1)
				_ = PlayerSingleData.InsertSingleResult(&user, single.Key, &player_single.SingleResult{
					Star:  star,
					Pass:  true,
					Score: score,
					Time:  time,
					Rank:  0,
				})
				user.SingleScore += score
				user.SingleStar += star

				// 更新关卡排行
				leaderboard, err := client.GetLeaderboard(single.LeaderboardKey)
				if err != nil {
					dwarf.Context.Error(err)
					return
				}
				leaderboardRank := rankService.GetInstance("maze", utils.ToString(leaderboard.Id), leaderboard.Asc)
				if _, err := client.UpdateLeaderboard(userOpen.Id, leaderboard, score); err != nil {
					return
				}
				if err := leaderboardRank.Update(userOpen.Id, score); err != nil {
					return
				}
			}
			if err := UserData.UpdateUser(&user, map[string]interface{}{
				"single_score": user.SingleScore,
				"single_star":  user.SingleStar,
			}); err != nil {
				dwarf.Context.Error(err)
				return
			}
			// 更新关卡排行
			if _, err := client.UpdateLeaderboard(userOpen.Id, singleLeaderboard, user.SingleScore); err != nil {
				dwarf.Context.Error(err)
				return
			}
			if err := singleLeaderboardRank.Update(userOpen.Id, user.SingleScore); err != nil {
				dwarf.Context.Error(err)
				return
			}
			onlineRank := onlineLeaderboardRank.Rank(userOpen.Id)
			singleRank := singleLeaderboardRank.Rank(userOpen.Id)
			dwarf.Context.Printf("Generate Player: %s, single: %d(%d), online: %d(%d)", userOpen.NickName, singleRank, user.SingleScore, onlineRank, user.OnlineScore)
		}
	},
}

func init() {
	Command.AddCommand(userCommand)
}

func InitEnv() error {
	var err error
	cnf = &maze.Config{}
	if err := galaxy.RegisterConfig("maze", cnf, true); err != nil {
		return err
	}
	if err := galaxy.InjectInterface(&ii); err != nil {
		return err
	}
	client, err = sdk.NewAppClient(dwarf.Context, ii.Boot, cnf.AppKey, cnf.AppSecret)
	if err != nil {
		return err
	}
	Env = game.NewEnvironment(dwarf.Context, "maze", client, ii.Boot.Cache("maze"))
	if err := Env.RegisterModule(player_model.Provider); err != nil {
		return err
	}
	if err := Env.RegisterModule(player_single.Provider); err != nil {
		return err
	}
	if err := Env.RegisterModule(model.Provider); err != nil {
		return err
	}
	Env.RegisterInit(func(env *game.Environment) error {
		// config
		if _, err := config.GetConfigData(Env, model.InitConfig); err != nil {
			return err
		}
		return nil
	})
	if err := Env.Start(); err != nil {
		return err
	}
	return nil
}
